package com.ccp.dev.workflow.service;

import com.ccp.dev.core.basic.base.BaseService;
import com.ccp.dev.core.basic.util.UUIDUtils;
import com.ccp.dev.core.util.BeanUtils;
import com.ccp.dev.core.util.Dom4jUtil;
import com.ccp.dev.core.util.XmlBeanUtil;
import com.ccp.dev.form.xml.util.MsgUtil;
import com.ccp.dev.form.xml.util.XmlUtil;
import com.ccp.dev.workflow.dao.AliasScriptDao;
import com.ccp.dev.workflow.model.AliasScript;
import com.ccp.dev.workflow.xml.AliasScriptXml;
import com.ccp.dev.workflow.xml.AliasScriptXmlList;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.dom4j.Document;
import org.dom4j.Element;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class AliasScriptService extends BaseService<AliasScript> {
    @Resource
    private AliasScriptDao aliasScriptDao;
    /**
     * 新增
     * @param aliasScript
     * */
    @Transactional(rollbackFor = Exception.class)
    public void addAliasScript(AliasScript aliasScript) {
        aliasScriptDao.add(aliasScript);
    }
    /**
     * 删除
     * @param lAryId
     * */
    @Transactional(rollbackFor = Exception.class)
    public void delByIds(String[] lAryId) {
        for (String id : lAryId){
            aliasScriptDao.delById(id);
        }
    }

    /**
     * 导入别名脚本XML
     * @param inputStream
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public void importXml(InputStream inputStream) throws Exception {
        Document doc = Dom4jUtil.loadXml(inputStream);
        Element root = doc.getRootElement();
        // 验证格式是否正确
        XmlUtil.checkXmlFormat(root, "system", "aliasScripts");

        String xmlStr = root.asXML();
        AliasScriptXmlList aliasScriptXmlList = (AliasScriptXmlList) XmlBeanUtil
                .unmarshall(xmlStr, AliasScriptXmlList.class);

        List<AliasScriptXml> list = aliasScriptXmlList.getAliasScriptXmlList();
        String msgError =null;
        for (AliasScriptXml aliasScriptXml : list) {
            // 导入表，并解析相关信息
             this.importAliasScriptXml(aliasScriptXml);

        }
    }
    /**
     * 导入时生成条件脚本
     * @param aliasScriptXml
     * @return
     * @throws Exception
     */
    private void importAliasScriptXml(AliasScriptXml aliasScriptXml)
            throws Exception {
        AliasScript aliasScript = aliasScriptXml.getAliasScript();
        //别名脚本是否能解析
        if (BeanUtils.isEmpty(aliasScript)) {
            throw new Exception();
        }
        String aliasName = aliasScript.getAliasName();
        boolean isRepeatName = this.checkRepeatName(null,aliasName);
        //别名脚本是否已存在
        if (isRepeatName) {
            //名称不存在，可以使用
            // 导入别名脚本
            aliasScript.setId(UUIDUtils.getUUIDFor32());
            aliasScriptDao.add(aliasScript);
        }else {
            //返回不能导入脚本的别名，报错内容为：别名脚本已经存在，请检查你的xml文件！
            throw new RuntimeException("‘" + aliasName + "’别名脚本已经存在，请检查你的xml文件！");
        }
    }


    /**
     * 脚本别名校验唯一性
     * @param id      只作用于编辑保存时过滤原数据
     * @param name    脚本别名
     * @return
     */
    public boolean checkRepeatName(String id, String name) {
        return aliasScriptDao.checkRepeatName(id,name) == 0;
    }

    /**
     * 导出全部别名脚本
     * @param aliasScripts
     * @return
     * @throws Exception
     */
    public String exportXml(List<AliasScript> aliasScripts) throws Exception {
        AliasScriptXmlList aliasScriptXmlList = new AliasScriptXmlList();
        List<AliasScriptXml> list = new ArrayList<AliasScriptXml>();
        for (AliasScript aliasScript : aliasScripts) {

            AliasScriptXml aliasScriptXml = this.exportAliasScriptXml(aliasScript);
            list.add(aliasScriptXml);
        }
        aliasScriptXmlList.setAliasScriptXmlList(list);
        return XmlBeanUtil.marshall(aliasScriptXmlList,
                AliasScriptXmlList.class);
    }


    /**
     * 导出别名脚本XML
     * @param tableIds
     *
     * @return
     * @throws Exception
     */
    public String exportXml(String[] tableIds) throws Exception {
        AliasScriptXmlList aliasScriptXmlList = new AliasScriptXmlList();
        List<AliasScriptXml> list = new ArrayList<AliasScriptXml>();
        for (int i = 0; i < tableIds.length; i++) {
            AliasScript aliasScript = aliasScriptDao.getById(tableIds[i]);
            AliasScriptXml aliasScriptXml = this.exportAliasScriptXml(aliasScript);
            list.add(aliasScriptXml);
        }
        aliasScriptXmlList.setAliasScriptXmlList(list);
        return XmlBeanUtil.marshall(aliasScriptXmlList,
                AliasScriptXmlList.class);
    }

    /**
     * 导出表的信息
     * @param aliasScript
     * @return
     */
    private AliasScriptXml exportAliasScriptXml(AliasScript aliasScript)throws Exception
    {
        AliasScriptXml aliasScriptXml=new AliasScriptXml();
        String id=aliasScript.getId();
        if(BeanUtils.isNotIncZeroEmpty(id)){
            //导出别名脚本
            aliasScriptXml.setAliasScript(aliasScript);
        }
        return aliasScriptXml;
    }

    /**
     * 通过类名获取类的所有方法
     * @param name
     * @return
     * @throws Exception
     */
    public JSONArray getMethodsByName(String name) throws Exception{
        JSONArray jarray = new JSONArray();
        Class<?> t = Class.forName(name);
        Method[] methods = t.getDeclaredMethods();
        for(Method method : methods){
            String returnType = method.getReturnType().getCanonicalName();
            Integer modifirer = method.getModifiers();
            //只要public方法
            if (modifirer != 1) {
                continue;
            }
            JSONObject jobMethod = new JSONObject();
            JSONArray jaryPara = new JSONArray();
            Class<?>[] paraArr = method.getParameterTypes();
            for(int i=0;i<paraArr.length;i++){
                Class<?> para = paraArr[i];
                String paraName = "arg" + i;
                String paraType = para.getCanonicalName();
                jaryPara.add(new JSONObject().accumulate("paraName", paraName)
                        .accumulate("paraType", paraType)
                        .accumulate("paraDesc", ""));
            }
            jobMethod.accumulate("returnType", returnType)
                        .accumulate("methodName", method.getName())
                    .accumulate("para", jaryPara);
            jarray.add(jobMethod);
        }
        return jarray;
    }
}
